<template>
	<a-popover v-model="visible" placement="bottomLeft" trigger="click">
		<template slot="title" class="antQuarterPicker">
			<div class="ant-calendar-month-panel-header">
				<a-icon type="double-left" @click="clickLast" aria-label="前一年" class="panel-prev-year-btn" />
				<a href="kavascript:;" role="button" class="ant-calendar-month-panel-year-select" @click="clickYear">{{ title }}</a>
				<a-icon type="double-right" @click="clickNext" aria-label="后一年" class="panel-next-year-btn" />
			</div>
		</template>
		<template slot="content">
			<div class="calendar">
				<div class="ant-calendar-body" style="margin:0px; width:100%">
					<table class="calendar-table">
						<tbody>
							<tr v-for="line in lineCount" :key="line">
								<td
									class="ant-calendar-month-panel-cell"
									v-for="index in line * 4 <= viewList.length ? 4 : viewList.length - (line - 1) * 4"
									:key="index"
									:class="{
										'ant-calendar-month-panel-selected-cell': viewList[(line - 1) * 4 + index - 1].active,
										'ant-calendar-month-panel-cell-disabled': viewList[(line - 1) * 4 + index - 1].disable
									}"
								>
									<a class="ant-calendar-month-panel-month" @click="clickItem(viewList[(line - 1) * 4 + index - 1])">
										{{ viewList[(line - 1) * 4 + index - 1].label }}
									</a>
								</td>
							</tr>
						</tbody>
					</table>
				</div>
			</div>
		</template>

		<a-input
			@change="changeText"
			@mouseenter.native="mouseEnter"
			@mouseleave.native="mouseLeave"
			:placeholder="placeholder"
			v-model="text"
			:readonly="!canEdit"
			:disabled="disabled"
			class="my-input"
		>
			<a-icon type="calendar" slot="suffix" class="ant-calendar-picker-icon" v-show="!showClear" />
			<a-icon type="close-circle" slot="suffix" v-show="showClear" class="ant-calendar-picker-icon ant-close-circle-icon" @click.stop="clear" />
		</a-input>
	</a-popover>
</template>

<script>
export default {
	name: 'ElQuarterPicker',
	props: {
		placeholder: {
			type: String,
			default: ''
		},
		size: {
			type: String,
			default: 'middle'
		},
		readonly: {
			type: Boolean,
			default: false
		},
		clearable: {
			type: Boolean,
			default: true
		},
		editable: {
			type: Boolean,
			default: true
		},
		disabled: {
			type: Boolean,
			default: false
		},
		format: {
			type: String,
			default: 'yyyy年第Q季度'
		},
		valueFormat: {
			type: String,
			default: 'yyyy-qq'
		},
		value: {
			type: String,
			default: ''
		}
	},
	model: {
		prop: 'value',
		event: 'change'
	},
	watch: {
		value(val) {
			// console.log('change-------', val)
			this.changeValue(val);
		},
		readonly(val) {
			this.canEdit = !val && this.editable;
			this.canPopover = !this.disabled && !val;
		},
		editable(val) {
			this.canEdit = !this.readonly && val;
		},
		disabled(val) {
			this.canPopover = !val && !this.readonly;
		}
	},
	data() {
		return {
			visible: false,
			showClear: false, // 控制清空按钮展示
			canEdit: true, // 是否可编辑
			canPopover: true, // 选择器弹出是否可用
			text: '', // 文本框值
			viewType: 1, // 视图类型，1季度，2年度
			viewYear: 0, // 当前年份
			viewList: [], // 数据列表
			lineCount: 0, // 数据行数
			title: '', // 选择器标题
			data: [0, 0] // 当前选择年度-季度
		};
	},
	mounted() {
		// console.log('mounted--------', this.value)
		this.changeValue(this.value);

		// 设置文本框是否可编辑
		this.canEdit = !this.readonly && this.editable;
		this.canPopover = !this.disabled && !this.readonly;

		// 监听按键(上下左右键可以切换季度)
		document.onkeydown = event => {
			if (this.visible) {
				const data = [this.data[0], this.data[1]];
				if (data[0] < 1 || data[1] < 1) {
					// 以当前季度为标准
					const curDate = new Date();
					data[0] = curDate.getFullYear();
					data[1] = parseInt(curDate.getMonth() / 3) + 1;
				}
				if (event.code === 'ArrowLeft') {
					// 上一个季度
					if (data[1] === 1) {
						data[0] = data[0] - 1;
						data[1] = 4;
					} else {
						data[1] = data[1] - 1;
					}
				} else if (event.code === 'ArrowRight') {
					// 下一个季度
					if (data[1] === 4) {
						data[0] = data[0] + 1;
						data[1] = 1;
					} else {
						data[1] = data[1] + 1;
					}
				} else if (event.code === 'ArrowUp') {
					// 上一年季度
					data[0] = data[0] - 1;
				} else if (event.code === 'ArrowDown') {
					// 下一年季度
					data[0] = data[0] + 1;
				} else {
					return;
				}

				// 超过年限的不处理
				if (data[0] < 1000 || data[0] > 9999) {
					return;
				}
				this.data = data;
				this.value = this.data[0] + '-0' + this.data[1];
				this.viewType = 1;
				this.viewYear = data[0];
				this.$emit('change', this.formatTo(data, this.valueFormat));
			}
		};
	},
	destroyed() {
		document.onkeydown = null;
	},
	methods: {
		// 季度文本变更
		changeText() {
			if (this.checkFormat(this.format, this.text)) {
				// 设置值
				this.formatFrom(this.text, this.format);
				this.$emit('change', this.formatTo(this.data, this.valueFormat));
			} else {
				// 输入了无效的格式，还原回原来的值
				if (this.data[0] < 1 || this.data[1] < 1) {
					this.text = undefined;
				} else {
					this.text = this.formatTo(this.data, this.format);
				}
			}
			this.visible = false;
		},
		// 鼠标进入
		mouseEnter() {
			if (!this.disabled && !this.readonly && this.clearable && this.text !== '') {
				this.showClear = true;
			}
		},
		// 鼠标离开
		mouseLeave() {
			if (!this.disabled && this.clearable) {
				this.showClear = false;
			}
		},
		// 清除季度
		clear() {
			this.showClear = false;
			this.visible = false;
			this.$emit('change', '');
		},
		// 季度值变更
		changeValue(val) {
			console.log('初始有值吗？' + val);
			this.viewType = 1;
			if (val) {
				// 反向格式化
				this.formatFrom(val, this.valueFormat);
				this.text = this.formatTo(this.data, this.format);
				this.viewYear = this.data[0];
			} else {
				//赋值初始值
				// this.text = ''
				this.viewYear = new Date().getFullYear();
				// const curQuarter = parseInt(new Date().getMonth() / 3) + 1;
				// this.data = [this.viewYear, curQuarter];
				// console.log('赋值初始值' + JSON.stringify(this.data));
				// //this.data = [0, 0]
				// this.text = this.formatTo(this.data, this.format);
				// this.changeText();
				this.data = [];
				this.text = undefined;
			}
			this.initView();
		},
		// 初始化视图数据
		initView() {
			const list = [];
			const curDate = new Date();
			const curYear = curDate.getFullYear();
			const curQuarter = parseInt(curDate.getMonth() / 3);
			if (this.viewType === 1) {
				let index = 0;
				for (const i of '一二三四') {
					index++;
					const item = { label: '第' + i + '季度', year: this.viewYear, quarter: index, current: false, active: false };
					if (this.viewYear === this.data[0] && index === this.data[1]) {
						item.active = true;
					}
					list.push(item);
				}
				if (!list.some(item => item.active)) {
					if (this.viewYear === curYear) {
						list[curQuarter].active = true;
					}
				}

				this.title = this.viewYear + ' 年';

				console.log('初始值：' + JSON.stringify(list));
			} else {
				const start = parseInt(this.viewYear / 10) * 10;
				this.viewYear = start;
				for (let i = 0; i < 10; i++) {
					const year = start + i;
					const item = { label: year + '', year: year, current: false, active: false, disable: false };
					if (year === curYear) {
						item.current = true;
					} else if (year === this.data[0]) {
						item.active = true;
					} else if (year > this.data[0]) {
						item.disable = true;
					}
					list.push(item);
				}
				this.title = start + ' 年 - ' + (start + 9) + ' 年';
			}
			this.viewList = list;
			console.log('初始视图：' + JSON.stringify(this.viewList));
			this.lineCount = parseInt(list.length / 4);
			if (list.length % 4 > 0) {
				this.lineCount++;
			}
		},
		// 校验季度格式是否正确
		checkFormat(pattern, val) {
			// 格式转成正则表达式
			let text = '';
			for (const char of pattern) {
				const dict = '\\^$.+?*[]{}!';
				if (dict.indexOf(char) === -1) {
					text += char;
				} else {
					text += '\\' + char;
				}
			}
			text = text.replace('yyyy', '[1-9]\\d{3}');
			text = text.replace('qq', '0[1-4]');
			text = text.replace('q', '[1-4]');
			text = text.replace('Q', '[一二三四]');
			text = '^' + text + '$';
			const patt = new RegExp(text);
			return patt.test(val);
		},
		// 格式化季度到指定格式
		formatTo(data, pattern) {
			let text = pattern.replace('yyyy', '' + data[0]);
			text = text.replace('qq', '0' + data[1]);
			text = text.replace('q', '' + data[1]);
			text = text.replace('Q', '一二三四'.substr(data[1] - 1, 1));
			return text;
		},
		// 以指定格式解析季度
		formatFrom(str, pattern) {
			const year = this.findText(str, pattern, 'yyyy');
			const quarter = this.findText(str, pattern, ['qq', 'q', 'Q']);
			this.data = [year, quarter];
		},
		// 查找文本数值
		findText(str, pattern, find) {
			if (find instanceof Array) {
				for (const f of find) {
					const val = this.findText(str, pattern, f);
					if (val !== -1) {
						return val;
					}
				}
				return -1;
			}
			const index = pattern.indexOf(find);
			if (index === -1) {
				return index;
			}
			const val = str.substr(index, find.length);
			if (find === 'Q') {
				return '一二三四'.indexOf(val) + 1;
			} else {
				return parseInt(val);
			}
		},
		// 年份点击
		clickYear() {
			if (this.viewType !== 1) {
				return;
			}
			// 切换年度选择器
			this.viewType = 2;
			this.initView();
		},
		// 季度选择
		clickItem(item) {
			if (!!item.disable) {
				return;
			}
			// console.log('select--------', item)
			if (this.viewType === 1) {
				// 选择季度
				this.$emit('change', this.formatTo([item.year, item.quarter], this.valueFormat));
				this.visible = false;
			} else {
				// 选择年度
				this.viewType = 1;
				this.viewYear = item.year;
				this.initView();
			}
		},
		// 上一年
		clickLast() {
			if (this.viewYear > 1000) {
				if (this.viewType === 1) {
					this.viewYear--;
					this.initView();
				} else {
					this.viewYear = this.viewYear - 10;
					this.initView();
				}
			}
		},
		// 下一年
		clickNext() {
			if (this.viewYear < 9999) {
				if (this.viewType === 1) {
					this.viewYear++;
					this.initView();
				} else {
					this.viewYear = this.viewYear + 10;
					this.initView();
				}
			}
		}
	}
};
</script>

<style lang="less" scoped>
.ant-calendar-month-panel-header {
	width: 100%;
	height: 40px;
	line-height: 40px;
	text-align: center;
	-webkit-user-select: none;
	-moz-user-select: none;
	-ms-user-select: none;
	user-select: none;
	i {
		cursor: pointer;
		font-size: 10px;
		position: absolute;
		// top: 18px;
		color: rgba(0, 0, 0, 0.45);
		font-family: Arial, 'Hiragino Sans GB', 'Microsoft Yahei', 'Microsoft Sans Serif', sans-serif;
		padding: 0 5px;
		display: inline-block;
		line-height: 40px;
	}
	.panel-prev-year-btn {
		left: 7px;
	}
	.panel-next-year-btn {
		right: 7px;
	}
}
.calendar {
	width: 280px;
	display: inline-block;
	.calendar-table {
		width: 100%;
	}
	tr td {
		width: 50%;
		display: inline-block;
		text-align: center;
		padding: 10px 0;
	}
	// td .cell {
	// 	color: rgba(0, 0, 0, 0.65);
	// 	text-align: center;
	// 	height: 24px;
	// 	line-height: 24px;
	// 	padding: 2px 8px;
	// 	border-radius: 2px;
	// 	-webkit-transition: background 0.3s ease;
	// 	transition: background 0.3s ease;
	// }

	// td .cell:hover {
	// 	background: #e6f7ff;
	// 	color: #1890ff;
	// 	cursor: pointer;
	// }

	// td.today .cell {
	// 	border: 1px solid #1890ff;
	// 	color: #1890ff;
	// }
	// td.current .cell {
	// 	background: #1890ff;
	// 	color: #fff;
	// }
}
.my-input {
	/deep/.ant-calendar-picker-icon {
		position: absolute;
		width: 14px;
		height: 14px;
		right: 0;
		top: 50%;
		margin-top: -7px;
		line-height: 14px;
		font-size: 14px;
		-webkit-transition: all 0.3s;
		transition: all 0.3s;
		-webkit-user-select: none;
		-moz-user-select: none;
		-ms-user-select: none;
		user-select: none;
		z-index: 1;
	}

	.ant-close-circle-icon {
		color: rgba(0, 0, 0, 0.45);
		cursor: pointer;
	}
}
</style>
<style type="text/css">
.ant-popover-placement-bottomLeft > .ant-popover-content > .ant-popover-arrow {
	display: none;
}
.ant-popover-title {
	padding: 0;
	border-bottom: none;
}
</style>
